Notebook for generating mutual rank (MR) clusters

library(boxr)
Welcome to boxr 0.3.4.99999!
Bug reports & Getting Help: https://github.com/brendan-R/boxr/issues
library(magrittr)
library(knitr)
library(limma)
library(snowfall)
Loading required package: snow
library(igraph)

Attaching package: ‘igraph’

The following object is masked from ‘package:magrittr’:

    %>%

The following objects are masked from ‘package:stats’:

    decompose, spectrum

The following object is masked from ‘package:base’:

    union
box_auth()
Reading client id from .Renviron
Reading client secret from .Renviron
Auto-refreshing stale OAuth token.
boxr: Authenticated at box.com as Julin Maloof (jnmaloof@ucdavis.edu)
box_setwd(24503987860)
box.com working directory changed to 'BrapaNetworks'

      id: 24503987860
    tree: All Files/BrapaNetworks
   owner: jnmaloof@ucdavis.edu
contents: 9 files, 0 folders
box_ls()

box.com remote object list (9 objects)

  Summary of first 9:

                            name type           id   size
1 Brapa2011BayesHeight_blups.csv file 164446516413  15 kB
2 Brapa2012BayesHeight_blups.csv file 164446639332  28 kB
3    Brapa_V1.5_annotated.csv.gz file 163054185089 2.7 MB
4   brassica_gene_clusters.RData file 164456845216 110 kB
5               CountsVoom.Rdata file 162362592785 240 MB
6         NormalizedCounts.RData file 162341539458 100 MB
7                RIL_TMM_CPM.csv file 162352229544 630 MB
8           RIL_v1.5_mapping.tsv file 162218089685 110 MB
9                     test.Rdata file 162921069376   64 B
                 owner
1 jnmaloof@ucdavis.edu
2 jnmaloof@ucdavis.edu
3 jnmaloof@ucdavis.edu
4 jnmaloof@ucdavis.edu
5 jnmaloof@ucdavis.edu
6 jnmaloof@ucdavis.edu
7 jnmaloof@ucdavis.edu
8 jnmaloof@ucdavis.edu
9 jnmaloof@ucdavis.edu


Use as.data.frame() to extract full results.

First attempt, use RIL means

Get data

annotation  <- read_csv("~/Box Sync/BrapaNetworks/Brapa_V1.5_annotated.csv.gz")
Error: could not find function "read_csv"

Summarize means

save(voom.fit,fil="~/Box Sync/BrapaNetworks/voom.fit.Rdata")
Error in save(voom.fit, fil = "~/Box Sync/BrapaNetworks/voom.fit.Rdata") : 
  object ‘~/Box Sync/BrapaNetworks/voom.fit.Rdata’ not found
RIL.coefs <- grep("RIL",colnames(coef(voom.fit)))
RIL.pvals <- topTable(voom.fit,coef = RIL.coefs,number = Inf)
sum(RIL.pvals$adj.P.Val<0.05)
[1] 26721
sum(RIL.pvals$adj.P.Val<10e-10) 
[1] 16596

So pretty much everything is highly significant

Start by taking the top 10000

genes.of.interest <- row.names(RIL.pvals)[1:10000]
expr.data <- voom.fit$coefficients[genes.of.interest,]
expr.data <- expr.data[,-grep("trt",colnames(expr.data))]
dim(expr.data)
[1] 10000   124
head(expr.data[,1:6])
          (Intercept) pdata$RILRIL_103 pdata$RILRIL_104 pdata$RILRIL_113
Bra001964    1.082235       -4.0321896     -4.091759090        3.6994071
Bra002728    5.767475       -0.5505380     -0.380674984       -3.2039164
Bra002785    7.202490       -0.4198373     -0.037837754       -1.9963410
Bra004960    4.733936       -3.8185006     -0.004181862       -0.2564264
Bra006384    4.969959       -6.8228958     -7.276735466       -0.3784078
Bra006411   -2.499584        6.3062481     -0.470837158        0.1143828
          pdata$RILRIL_115 pdata$RILRIL_12
Bra001964       0.01722016      0.64266465
Bra002728      -0.60526951     -0.81853556
Bra002785      -0.04677711     -0.05993573
Bra004960       0.14101788     -0.22825526
Bra006384      -8.39926386     -7.41766487
Bra006411      -0.72175621     -1.10891611
expr.data[,-1] <- expr.data[,-1] + expr.data[,1] # add the intercept to the coefficients
colnames(expr.data) <- sub("pdata$RIL","",colnames(expr.data),fixed=TRUE)
head(expr.data[,1:6])
          (Intercept)    RIL_103   RIL_104   RIL_113   RIL_115    RIL_12
Bra001964    1.082235 -2.9499545 -3.009524  4.781642  1.099455  1.724900
Bra002728    5.767475  5.2169367  5.386800  2.563558  5.162205  4.948939
Bra002785    7.202490  6.7826522  7.164652  5.206149  7.155712  7.142554
Bra004960    4.733936  0.9154359  4.729755  4.477510  4.874954  4.505681
Bra006384    4.969959 -1.8529365 -2.306776  4.591552 -3.429305 -2.447706
Bra006411   -2.499584  3.8066642 -2.970421 -2.385201 -3.221340 -3.608500

Get Rob’s Data

blups2011 <- box_read_csv(164446516413)
Remote file '/var/folders/xr/9cbydt955pj42zfq6mc_y5g40000gn/T//Rtmp7o2lKa/Brapa2011BayesHeight_blups.csv' read into memory as an object of class data.frame
blups2012 <- box_read_csv(164446639332)
Remote file '/var/folders/xr/9cbydt955pj42zfq6mc_y5g40000gn/T//Rtmp7o2lKa/Brapa2012BayesHeight_blups.csv' read into memory as an object of class data.frame
blups2011$Line %<>% paste("RIL",.,sep="_")
blups2012$Line %<>% paste("RIL",.,sep="_")
blups2011 %<>% subset(select=!grepl("V1|individual|blk|trt|treat",colnames(.)))
blups2012 %<>% subset(select=!grepl("V1|individual|blk|trt|treat",colnames(.)))
head(blups2011)
head(blups2012)

Merge Data

expr.blup.2011 <- merge(blups2011,t(expr.data),by.x="Line",by.y=0)
expr.blup.2012 <- merge(blups2012,t(expr.data),by.x="Line",by.y=0)
head(expr.blup.2011)
head(expr.blup.2012)

Correlation

expr.blup.2011.cor <- cor(expr.blup.2011[,-1])
expr.blup.2012.cor <- cor(expr.blup.2012[,-1])

Mutual Rank

sfStop()

Stopping cluster
save(blups2011,blups2012,voom.fit,expr.blup.2011, expr.blup.2012,expr.blup.2011.mr, expr.blup.2012.mr,file = "~/Box Sync/BrapaNetworks/MR.Rdata")

Get graphs at different MR

First: define some functions

Get blup networks at different MR thresholds

Use different MR thresholds of 10 to 210 (absolute values) to build the network (genes with a correlation higher than the threshold were considered connected). I then subset the network to take all genes “directly” connected to LFY.

plots

null device 
          1 
null device 
          1 
LS0tCnRpdGxlOiAiTVIgQ2x1c3RlcmluZyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKTm90ZWJvb2sgZm9yIGdlbmVyYXRpbmcgbXV0dWFsIHJhbmsgKE1SKSBjbHVzdGVycwoKYGBge3J9CmxpYnJhcnkoYm94cikKbGlicmFyeShtYWdyaXR0cikKbGlicmFyeShrbml0cikKbGlicmFyeShsaW1tYSkKbGlicmFyeShzbm93ZmFsbCkKbGlicmFyeShpZ3JhcGgpCmJveF9hdXRoKCkKYm94X3NldHdkKDI0NTAzOTg3ODYwKQpib3hfbHMoKQpgYGAKCiMjIyBGaXJzdCBhdHRlbXB0LCB1c2UgUklMIG1lYW5zCkdldCBkYXRhCmBgYHtyfQojYm94X2xvYWQoMTYyMzYyNTkyNzg1KQpsb2FkKCJ+L0JveCBTeW5jL0JyYXBhTmV0d29ya3MvQ291bnRzVm9vbS5SZGF0YSIpCmFubm90YXRpb24gIDwtIHJlYWQuY3N2KCJ+L0JveCBTeW5jL0JyYXBhTmV0d29ya3MvQnJhcGFfVjEuNV9hbm5vdGF0ZWQuY3N2Lmd6IikKYGBgCgpTdW1tYXJpemUgbWVhbnMKYGBge3J9CnN0cihjb3VudHMudm9vbSkKc3VtbWFyeShjb3VudHMudm9vbSkKdm9vbS5maXQgPC0gbG1GaXQoY291bnRzLnZvb20sZGVzaWduPWNvdW50cy52b29tJGRlc2lnbikgI2FkZGl0aXZlIGRlc2lnbiBpcyBhbHJlYWR5IHRoZXJlCnZvb20uZml0IDwtIGVCYXllcyh2b29tLmZpdCkKc2F2ZSh2b29tLmZpdCxmaWxlPSJ+L0JveCBTeW5jL0JyYXBhTmV0d29ya3Mvdm9vbS5maXQuUmRhdGEiKQpgYGAKCgpgYGB7cn0KUklMLmNvZWZzIDwtIGdyZXAoIlJJTCIsY29sbmFtZXMoY29lZih2b29tLmZpdCkpKQpSSUwucHZhbHMgPC0gdG9wVGFibGUodm9vbS5maXQsY29lZiA9IFJJTC5jb2VmcyxudW1iZXIgPSBJbmYpCnN1bShSSUwucHZhbHMkYWRqLlAuVmFsPDAuMDUpCnN1bShSSUwucHZhbHMkYWRqLlAuVmFsPDEwZS0xMCkgCmBgYApTbyBwcmV0dHkgbXVjaCBldmVyeXRoaW5nIGlzIGhpZ2hseSBzaWduaWZpY2FudAoKU3RhcnQgYnkgdGFraW5nIHRoZSB0b3AgMTAwMDAKCmBgYHtyfQpnZW5lcy5vZi5pbnRlcmVzdCA8LSByb3cubmFtZXMoUklMLnB2YWxzKVsxOjEwMDAwXQpleHByLmRhdGEgPC0gdm9vbS5maXQkY29lZmZpY2llbnRzW2dlbmVzLm9mLmludGVyZXN0LF0KZXhwci5kYXRhIDwtIGV4cHIuZGF0YVssLWdyZXAoInRydCIsY29sbmFtZXMoZXhwci5kYXRhKSldCmRpbShleHByLmRhdGEpCmhlYWQoZXhwci5kYXRhWywxOjZdKQpgYGAKCmBgYHtyfQpleHByLmRhdGFbLC0xXSA8LSBleHByLmRhdGFbLC0xXSArIGV4cHIuZGF0YVssMV0gIyBhZGQgdGhlIGludGVyY2VwdCB0byB0aGUgY29lZmZpY2llbnRzCmNvbG5hbWVzKGV4cHIuZGF0YSkgPC0gc3ViKCJwZGF0YSRSSUwiLCIiLGNvbG5hbWVzKGV4cHIuZGF0YSksZml4ZWQ9VFJVRSkKaGVhZChleHByLmRhdGFbLDE6Nl0pCmBgYAoKR2V0IFJvYidzIERhdGEKYGBge3J9CmJsdXBzMjAxMSA8LSBib3hfcmVhZF9jc3YoMTY0NDQ2NTE2NDEzKQpibHVwczIwMTIgPC0gYm94X3JlYWRfY3N2KDE2NDQ0NjYzOTMzMikKYmx1cHMyMDExJExpbmUgJTw+JSBwYXN0ZSgiUklMIiwuLHNlcD0iXyIpCmJsdXBzMjAxMiRMaW5lICU8PiUgcGFzdGUoIlJJTCIsLixzZXA9Il8iKQpibHVwczIwMTEgJTw+JSBzdWJzZXQoc2VsZWN0PSFncmVwbCgiVjF8aW5kaXZpZHVhbHxibGt8dHJ0fHRyZWF0Iixjb2xuYW1lcyguKSkpCmJsdXBzMjAxMiAlPD4lIHN1YnNldChzZWxlY3Q9IWdyZXBsKCJWMXxpbmRpdmlkdWFsfGJsa3x0cnR8dHJlYXQiLGNvbG5hbWVzKC4pKSkKaGVhZChibHVwczIwMTEpCmhlYWQoYmx1cHMyMDEyKQpgYGAKCk1lcmdlIERhdGEKYGBge3J9CmV4cHIuYmx1cC4yMDExIDwtIG1lcmdlKGJsdXBzMjAxMSx0KGV4cHIuZGF0YSksYnkueD0iTGluZSIsYnkueT0wKQpleHByLmJsdXAuMjAxMiA8LSBtZXJnZShibHVwczIwMTIsdChleHByLmRhdGEpLGJ5Lng9IkxpbmUiLGJ5Lnk9MCkKaGVhZChleHByLmJsdXAuMjAxMSkKaGVhZChleHByLmJsdXAuMjAxMikKYGBgCgpDb3JyZWxhdGlvbgpgYGB7cn0KZXhwci5ibHVwLjIwMTEuY29yIDwtIGNvcihleHByLmJsdXAuMjAxMVssLTFdKQpleHByLmJsdXAuMjAxMi5jb3IgPC0gY29yKGV4cHIuYmx1cC4yMDEyWywtMV0pCmBgYAoKTXV0dWFsIFJhbmsKYGBge3J9CnNmSW5pdChwYXJhbGxlbCA9IFRSVUUsIGNwdXM9NCkKCmV4cHIuYmx1cC4yMDExLnJhbmsgPC0gc2ZBcHBseShleHByLmJsdXAuMjAxMS5jb3IsMixmdW5jdGlvbih4KSByYW5rKC1hYnMoeCkpKQpleHByLmJsdXAuMjAxMS5yYW5rWzE6MTAsMToxMF0KZXhwci5ibHVwLjIwMTEubXIgPC0gc3FydChleHByLmJsdXAuMjAxMS5yYW5rKnQoZXhwci5ibHVwLjIwMTEucmFuaykpCmV4cHIuYmx1cC4yMDExLm1yWzE6MTAsMToxMF0KCmV4cHIuYmx1cC4yMDEyLnJhbmsgPC0gc2ZBcHBseShleHByLmJsdXAuMjAxMi5jb3IsMixmdW5jdGlvbih4KSByYW5rKC1hYnMoeCkpKQpleHByLmJsdXAuMjAxMi5yYW5rWzE6MTAsMToxMF0KZXhwci5ibHVwLjIwMTIubXIgPC0gc3FydChleHByLmJsdXAuMjAxMi5yYW5rKnQoZXhwci5ibHVwLjIwMTIucmFuaykpCmV4cHIuYmx1cC4yMDEyLm1yWzE6MTAsMToxMF0KCnNmU3RvcCgpCmBgYAoKCmBgYHtyfQpzYXZlKGJsdXBzMjAxMSxibHVwczIwMTIsdm9vbS5maXQsZXhwci5ibHVwLjIwMTEsIGV4cHIuYmx1cC4yMDEyLGV4cHIuYmx1cC4yMDExLm1yLCBleHByLmJsdXAuMjAxMi5tcixmaWxlID0gIn4vQm94IFN5bmMvQnJhcGFOZXR3b3Jrcy9NUi5SZGF0YSIpCmBgYAoKR2V0IGdyYXBocyBhdCBkaWZmZXJlbnQgTVIKCkZpcnN0OiBkZWZpbmUgc29tZSBmdW5jdGlvbnMKIApgYGB7ciBtcl9zdWJncmFwaHMsIGVjaG89RkFMU0UsIGNhY2hlLmxhenk9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGV2YWw9VFJVRSB9CmxvYWQoIn4vQm94IFN5bmMvQnJhcGFOZXR3b3Jrcy9NUi5SZGF0YSIpCmdldC5tci5zdWJncmFwaCA8LSBmdW5jdGlvbihtci5jdXRvZmYsbXIubWF0cml4LGFubm90YXRpb249TkEsbmVpZ2hib3Job29kLG9yZGVyPTEpIHsKICAjZnVuY3Rpb24gdG8gZXh0cmFjdCBMRlkgZ3JhcGggYXQgYSBzcGVjaWZpY2VkIGNvcnJlbGF0aW9uIGN1dG9mZgogIGdlbmUubXIudG1wIDwtIG1yLm1hdHJpeAogIGdlbmUubXIudG1wW2FicyhnZW5lLm1yLnRtcCkgPiBtci5jdXRvZmZdIDwtIDAKICBnZW5lLm1yLnRtcFtpcy5uYShnZW5lLm1yLnRtcCldIDwtIDAgI2ltcG9ydGFudCEgb3RoZXJ3aXNlIHZlcnRpY2VzIHdpdGggTkEgZWRnZXMgYXJlIGNvbm5lY3RlZAogIAogIGdlbmUuZ3JhcGggPC0gZ3JhcGguYWRqYWNlbmN5KGFkam1hdHJpeCA9IGdlbmUubXIudG1wLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGU9InVuZGlyZWN0ZWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdlaWdodGVkPSJtciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlhZz1GQUxTRSkKICAKICAjY2x1c3QubWVtYmVyc2hpcCA8LSBjbHVzdGVycyhnZW5lLmdyYXBoKSRtZW1iZXJzaGlwCiAgCiAgI2NvbGJhciA8LSByYWluYm93KG1heChjbHVzdC5tZW1iZXJzaGlwKSsxKSAgICAgICAgICAgICAgICAgI2RlZmluZSBjb2xvcnMKICAjVihnZW5lLmdyYXBoKSRjb2xvciA8LSBjb2xiYXJbY2x1c3QubWVtYmVyc2hpcCsxXSAgICAgICAgICAgICAjYXNzaWduIGNvbG9ycyB0byBub2RlcwogIHN1Yi5ncmFwaHMgPC0gZ3JhcGgubmVpZ2hib3Job29kKGdlbmUuZ3JhcGgsb3JkZXI9b3JkZXIsbm9kZXM9bmVpZ2hib3Job29kKSAjZm9yIGVhY2ggbmRvZSBvZiBpbnRlcmVzdCBnZXQgYWxsIG90aGVyIG5vZGVzIHdpdGhpbiBvcmRlciBvZiAxCiAgCiAgI2dldCBjb21ibmluZWQgbGlzdCBvZiB2ZXJ0aWNlcy4uLgogIAogIHN1Yi52ZXJ0aWNlcyA8LSB1bmlxdWUobmFtZXModW5saXN0KHNhcHBseShzdWIuZ3JhcGhzLCBWKSkpKQogIAogIGNvbWJpbmVkLnN1Yi5ncmFwaCA8LSBpbmR1Y2VkX3N1YmdyYXBoKGdlbmUuZ3JhcGgsc3ViLnZlcnRpY2VzKQogIAogIFYoY29tYmluZWQuc3ViLmdyYXBoKSRjb2xvciA8LSAibGlnaHRibHVlIgogIFYoY29tYmluZWQuc3ViLmdyYXBoKVtuZWlnaGJvcmhvb2RdJGNvbG9yIDwtICJyZWQiCiAgaWYoIWlzLm5hKGFubm90YXRpb24pKSBWKGNvbWJpbmVkLnN1Yi5ncmFwaCkkZ2VuZSA8LSBhbm5vdGF0aW9uJFNZTUJPTFttYXRjaChWKGNvbWJpbmVkLnN1Yi5ncmFwaCkkbmFtZSxhbm5vdGF0aW9uJFRBSVIpXQogIGxpc3QoY3V0b2ZmPW1yLmN1dG9mZixncmFwaD1jb21iaW5lZC5zdWIuZ3JhcGgpCiAgfQpgYGAKCiMjIEdldCBibHVwIG5ldHdvcmtzIGF0IGRpZmZlcmVudCBNUiB0aHJlc2hvbGRzClVzZSBkaWZmZXJlbnQgTVIgdGhyZXNob2xkcyBvZiAxMCB0byAyMTAgKGFic29sdXRlIHZhbHVlcykgdG8gYnVpbGQgdGhlIG5ldHdvcmsgKGdlbmVzIHdpdGggYSBjb3JyZWxhdGlvbiBoaWdoZXIgdGhhbiB0aGUgdGhyZXNob2xkIHdlcmUgY29uc2lkZXJlZCBjb25uZWN0ZWQpLiAgSSB0aGVuIHN1YnNldCB0aGUgbmV0d29yayB0byB0YWtlIGFsbCBnZW5lcyAiZGlyZWN0bHkiIGNvbm5lY3RlZCB0byBMRlkuCgpgYGB7ciBsZnlfc3ViLCBlY2hvPUZBTFNFLCBldmFsPUZBTFNFfQpjdXRvZmZzIDwtIGMoMTAsMjAsMzAsNTAsODAsMTAwLDEzMCwyMTApCmJsdXAubXIuZ3JhcGhzLjIwMTEgPC0gbGFwcGx5KGN1dG9mZnMsIGdldC5tci5zdWJncmFwaCwgbXIubWF0cml4ID0gZXhwci5ibHVwLjIwMTEubXIsIGFubm90YXRpb249IE5BLCBuZWlnaGJvcmhvb2QgPSBjb2xuYW1lcyhibHVwczIwMTEpWy0xXSkKbmFtZXMoYmx1cC5tci5ncmFwaHMuMjAxMSkgPC0gc2FwcGx5KGJsdXAubXIuZ3JhcGhzLjIwMTEsIGZ1bmN0aW9uKHgpIHBhc3RlKCJibHVwLm1yLmdyYXBoLjIwMTEiLHgkY3V0b2ZmLHNlcD0iLiIpKQoKYmx1cC5tci5ncmFwaHMuMjAxMiA8LSBsYXBwbHkoY3V0b2ZmcywgZ2V0Lm1yLnN1YmdyYXBoLCBtci5tYXRyaXggPSBleHByLmJsdXAuMjAxMi5tciwgYW5ub3RhdGlvbj0gTkEsIG5laWdoYm9yaG9vZCA9IGNvbG5hbWVzKGJsdXBzMjAxMilbLTFdKQpuYW1lcyhibHVwLm1yLmdyYXBocy4yMDEyKSA8LSBzYXBwbHkoYmx1cC5tci5ncmFwaHMuMjAxMiwgZnVuY3Rpb24oeCkgcGFzdGUoImJsdXAubXIuZ3JhcGguMjAxMiIseCRjdXRvZmYsc2VwPSIuIikpCmBgYAoKIyMgcGxvdHMKCmBgYHtyIHBsb3QsIGVjaG89RkFMU0UsIGNhY2hlPVRSVUV9CmN1dG9mZj0yMDAKcGRmKCJibHVwLm1yLnBsb3RzLjIwMTEucGRmIixoZWlnaHQ9MTIsd2lkdGg9MTIpCnJlc3VsdCA8LSBzYXBwbHkoYmx1cC5tci5ncmFwaHMuMjAxMSxmdW5jdGlvbiAoYmx1cC5ncmFwaCkgewogIGlmKGJsdXAuZ3JhcGgkY3V0b2ZmIDw9IGN1dG9mZikgewogICAgRShibHVwLmdyYXBoJGdyYXBoKSR3ZWlnaHQgPC0gcmFuayhFKGJsdXAuZ3JhcGgkZ3JhcGgpJG1yKV4oMS80KQogICAgcGxvdChibHVwLmdyYXBoJGdyYXBoLAogICAgICAgICBsYXlvdXQgPSBsYXlvdXRfd2l0aF9raywgCiAgICAgICAgIHZlcnRleC5sYWJlbCA9ICNpZmVsc2UoaXMubmEoVihibHVwLmdyYXBoJGdyYXBoKSRnZW5lKXxWKGJsdXAuZ3JhcGgkZ3JhcGgpJGdlbmU9PSIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVihibHVwLmdyYXBoJGdyYXBoKSRuYW1lICwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgICBWKGJsdXAuZ3JhcGgkZ3JhcGgpJGdlbmUpLAogICAgICAgICB2ZXJ0ZXgubGFiZWwuY2V4PTEsCiAgICAgICAgIG1haW49cGFzdGUoIk1SIGN1dG9mZiA9IixzdWIoImJsdXAubXIuZ3JhcGguIiwiIixibHVwLmdyYXBoJGN1dG9mZixmaXhlZD1UKSkpCiAgICBybShibHVwLmdyYXBoKQogICAgfQogIH0pCmRldi5vZmYoKQoKY3V0b2ZmPTIwMApwZGYoImJsdXAubXIucGxvdHMuMjAxMi5wZGYiLGhlaWdodD0xMix3aWR0aD0xMikKcmVzdWx0IDwtIHNhcHBseShibHVwLm1yLmdyYXBocy4yMDEyLGZ1bmN0aW9uIChibHVwLmdyYXBoKSB7CiAgaWYoYmx1cC5ncmFwaCRjdXRvZmYgPD0gY3V0b2ZmKSB7CiAgICBFKGJsdXAuZ3JhcGgkZ3JhcGgpJHdlaWdodCA8LSByYW5rKEUoYmx1cC5ncmFwaCRncmFwaCkkbXIpXigxLzQpCiAgICBwbG90KGJsdXAuZ3JhcGgkZ3JhcGgsCiAgICAgICAgIGxheW91dCA9IGxheW91dF93aXRoX2trLCAKICAgICAgICAgdmVydGV4LmxhYmVsID0gI2lmZWxzZShpcy5uYShWKGJsdXAuZ3JhcGgkZ3JhcGgpJGdlbmUpfFYoYmx1cC5ncmFwaCRncmFwaCkkZ2VuZT09IiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBWKGJsdXAuZ3JhcGgkZ3JhcGgpJG5hbWUgLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAgIFYoYmx1cC5ncmFwaCRncmFwaCkkZ2VuZSksCiAgICAgICAgIHZlcnRleC5sYWJlbC5jZXg9MSwKICAgICAgICAgbWFpbj1wYXN0ZSgiTVIgY3V0b2ZmID0iLHN1YigiYmx1cC5tci5ncmFwaC4iLCIiLGJsdXAuZ3JhcGgkY3V0b2ZmLGZpeGVkPVQpKSkKICAgIHJtKGJsdXAuZ3JhcGgpCiAgICB9CiAgfSkKZGV2Lm9mZigpCmBgYA==